#include <Math.h>
#include "AnalogSubcircuit.h"


///////////////////////////////////////////////////////////////////////////////
//
// Function:   BJT_BuildAC
//
// Overview:   Builds AC simulation for the specified BJT.
//
// Arguments:  pobjBJT [IN] A pointer to the structure of the specified BJT.
//             fOmega  [IN] Omega factor.
//
///////////////////////////////////////////////////////////////////////////////

void BJT_BuildAC (stBJT* pobjBJT, float fOmega)
{
   if (pobjBJT->icoll != pobjBJT->coll)
      CONDUCTANCE(pobjBJT->icoll, pobjBJT->coll, pobjBJT->yc);
    
   if (pobjBJT->ibase != pobjBJT->base)
      CONDUCTANCE(pobjBJT->ibase, pobjBJT->base, pobjBJT->yb);

   if (pobjBJT->iemit != pobjBJT->emit)
      CONDUCTANCE(pobjBJT->iemit, pobjBJT->emit, pobjBJT->ye);

   CONDUCTANCE(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->dbc.yn * pobjBJT->brx);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->dbe.yn * pobjBJT->bfx);
   TRANSCONDUCTANCE(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->iemit, pobjBJT->icoll, pobjBJT->dbc.yn);
   TRANSCONDUCTANCE(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->icoll, pobjBJT->iemit, pobjBJT->dbe.yn);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->dbes.yn);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->dbcs.yn);

   if (pobjBJT->cje >= 1e-18 || pobjBJT->tfv >= 1e-18)
      SetCapacitorAC(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->cjev, fOmega);
   
   if (pobjBJT->cjc >= 1e-18 || pobjBJT->objParameters.tr >= 1e-18)
      SetCapacitorAC(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->cjcv, fOmega);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   BJT_BuildDC
//
// Overview:   Builds DC simulation for the specified BJT.
//
// Arguments:  pobjBJT   [IN] A pointer to the structure of the specified BJT.
//             fSimTime  [IN] Simulation step time.
//             wMode     [IN] Mode of simulation.
//
///////////////////////////////////////////////////////////////////////////////

void BJT_BuildDC (stBJT* pobjBJT, float fSimTime, WORD wMode)
{
   if (pobjBJT->icoll != pobjBJT->coll)
	   CONDUCTANCE(pobjBJT->icoll, pobjBJT->coll, pobjBJT->yc);
   
   if (pobjBJT->ibase != pobjBJT->base)
	   CONDUCTANCE(pobjBJT->ibase, pobjBJT->base, pobjBJT->yb);
   
   if (pobjBJT->iemit != pobjBJT->emit)
	   CONDUCTANCE(pobjBJT->iemit, pobjBJT->emit, pobjBJT->ye);

   if (wMode & ITERATE)
	{
      InternalDiode(pobjBJT->is, pobjBJT->vkf, pobjBJT->objParameters.nf * g_fVtVolt, pobjBJT->vbe * pobjBJT->iPolarity, &pobjBJT->dbe);
      InternalDiode(pobjBJT->is, pobjBJT->vkr, pobjBJT->objParameters.nr * g_fVtVolt, pobjBJT->vbc * pobjBJT->iPolarity, &pobjBJT->dbc);
      InternalDiode(pobjBJT->ise, pobjBJT->vke, pobjBJT->objParameters.ne * g_fVtVolt, pobjBJT->vbe * pobjBJT->iPolarity, &pobjBJT->dbes);
      InternalDiode(pobjBJT->isc, pobjBJT->vkc, pobjBJT->objParameters.nc * g_fVtVolt, pobjBJT->vbc * pobjBJT->iPolarity, &pobjBJT->dbcs);

      pobjBJT->tfv = pobjBJT->objParameters.tf;
      
      if (pobjBJT->objParameters.tf && pobjBJT->objParameters.xtf)
      {
         double x = pobjBJT->dbe.in + pobjBJT->vbe * pobjBJT->iPolarity * pobjBJT->dbe.yn;
        
         x = x / (x + pobjBJT->objParameters.itf);
         pobjBJT->tfv *= (float)(1 + pobjBJT->objParameters.xtf * ((3 - 2 * x) * x * x * exp(pobjBJT->vbc * pobjBJT->iPolarity / (1.44 * pobjBJT->objParameters.vtf))));
      }
   }

   DC_CURRENT(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->dbc.in * pobjBJT->iPolarity * pobjBJT->brx);
   DC_CURRENT(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->dbe.in * pobjBJT->iPolarity * pobjBJT->bfx);
   DC_CURRENT(pobjBJT->iemit, pobjBJT->icoll, (pobjBJT->dbc.in - pobjBJT->dbe.in) * pobjBJT->iPolarity);
   DC_CURRENT(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->dbes.in * pobjBJT->iPolarity);
   DC_CURRENT(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->dbcs.in * pobjBJT->iPolarity);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->dbc.yn * pobjBJT->brx);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->dbe.yn * pobjBJT->bfx);
   TRANSCONDUCTANCE(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->iemit, pobjBJT->icoll, pobjBJT->dbc.yn);
   TRANSCONDUCTANCE(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->icoll, pobjBJT->iemit, pobjBJT->dbe.yn);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->dbes.yn);
   CONDUCTANCE(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->dbcs.yn);

   if (pobjBJT->cje >= 1e-18 || pobjBJT->tfv >= 1e-18)
   {
      if (wMode & ITERATE)
         pobjBJT->cjev = PN_Capacitor(pobjBJT->cje, pobjBJT->tfv, pobjBJT->objParameters.mje, pobjBJT->objParameters.fc, pobjBJT->vje,
            pobjBJT->is, 0, 0, (float)pobjBJT->vbe * pobjBJT->iPolarity);
      SetCapacitorDC(pobjBJT->ibase, pobjBJT->iemit, pobjBJT->cjev, &pobjBJT->be_cap, fSimTime, wMode);
   }
    
   if (pobjBJT->cjc >= 1e-18 || pobjBJT->objParameters.tr >= 1e-18)
   {
      if (wMode & ITERATE)
         pobjBJT->cjcv = PN_Capacitor(pobjBJT->cjc, pobjBJT->objParameters.tr, pobjBJT->objParameters.mjc, pobjBJT->objParameters.fc, pobjBJT->vjc,
            pobjBJT->is, 0, 0, (float)pobjBJT->vbc * pobjBJT->iPolarity);
      SetCapacitorDC(pobjBJT->ibase, pobjBJT->icoll, pobjBJT->cjcv, &pobjBJT->bc_cap, fSimTime, wMode);
   }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   BJT_ErrorCheck
//
// Overview:   Check for possible error in calculation.
//
// Arguments:  pobjBJT [IN] A reference to the structure of the specified BJT.
//
///////////////////////////////////////////////////////////////////////////////

void BJT_ErrorCheck (stBJT* pobjBJT, double* pdVoltError)
{  
   MaxErrEx(pobjBJT->ibase, pobjBJT->iemit, &pobjBJT->vbe, pdVoltError);
   MaxErrEx(pobjBJT->ibase, pobjBJT->icoll, &pobjBJT->vbc, pdVoltError);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   BJT_InitIntNodes
//
// Overview:   Initializes the specified BJT.
//
// Arguments:  pobjBJT         [IN] A referernce to working structure of diode.
//             iInternalAnode  [IN] An internal anode number.
//
// Returns:    0 - The internal anode wasn't created.
//             1 - The internal anode was created successfully.
//
///////////////////////////////////////////////////////////////////////////////

int BJT_InitIntNodes (stBJT* pobjBJT, int iCollerctor, int iBase, int iEmitter,
                      int iInternalNode)
{
   int iNodes = 0;
   
   pobjBJT->coll = iCollerctor;
   pobjBJT->base = iBase;
   pobjBJT->emit = iEmitter;

   pobjBJT->icoll = iCollerctor;
   pobjBJT->ibase = iBase;
   pobjBJT->iemit = iEmitter;

   if (pobjBJT->objParameters.rc >= 1e-6)
   {
      pobjBJT->yc    = (float)(1.0 / pobjBJT->objParameters.rc);
      pobjBJT->icoll = iInternalNode + iNodes++;
   }

   if (pobjBJT->objParameters.rb >= 1e-6)
   {
      pobjBJT->yb    = (float)(1.0 / pobjBJT->objParameters.rb);
      pobjBJT->ibase = iInternalNode + iNodes++;
   }

   if (pobjBJT->objParameters.re >= 1e-6)
   {
      pobjBJT->ye    = (float)(1.0 / pobjBJT->objParameters.re);
      pobjBJT->iemit = iInternalNode + iNodes++;
   }
   
   return iNodes;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   BJT_InitSim
//
// Overview:   Initializes the specified BJT.
//
// Arguments:  iAnode       [IN]  A port number of the anode.
//             iCathode     [IN]  A port number of the cathode.
//             iInitLCMode  [IN]  Kind of initialization.
//             pobjBJT      [OUT] A pointer to the structure of the specified
//                                BJT to be intialized.
//             iPolarity    [IN]  The polarity of transistor (NPN or PNP).
//
///////////////////////////////////////////////////////////////////////////////

void BJT_InitSim (int iInitLCMode, stBJT* pobjBJT, int iPolarity)
{
   pobjBJT->iPolarity = iPolarity;

   SetTemp();
   
   pobjBJT->is  = Temp_is(pobjBJT->objParameters.is, 1.0, pobjBJT->objParameters.eg, pobjBJT->objParameters.xti);
   pobjBJT->ise = pobjBJT->objParameters.ise;
   
   if (pobjBJT->objParameters.ise > 1)
      pobjBJT->ise *= pobjBJT->objParameters.is;

   pobjBJT->ise = Temp_is(pobjBJT->ise, pobjBJT->objParameters.ne, pobjBJT->objParameters.eg, pobjBJT->objParameters.xti) / Temp_brf(1, pobjBJT->objParameters.xtb);
   pobjBJT->isc = pobjBJT->objParameters.isc;
   
   if (pobjBJT->objParameters.isc > 1)
      pobjBJT->isc *= pobjBJT->objParameters.is;

   pobjBJT->isc = Temp_is(pobjBJT->isc, pobjBJT->objParameters.nc, pobjBJT->objParameters.eg, pobjBJT->objParameters.xti) / Temp_brf(1, pobjBJT->objParameters.xtb);
   pobjBJT->vje = Temp_vj(pobjBJT->objParameters.vje);
   pobjBJT->vjc = Temp_vj(pobjBJT->objParameters.vjc);
   pobjBJT->cje = Temp_cj(pobjBJT->objParameters.cje, pobjBJT->objParameters.mje, pobjBJT->vje / pobjBJT->objParameters.vje);
   pobjBJT->cjc = Temp_cj(pobjBJT->objParameters.cjc, pobjBJT->objParameters.mjc, pobjBJT->vjc / pobjBJT->objParameters.vjc);

   pobjBJT->bfx = 1 / Temp_brf(pobjBJT->objParameters.bf, pobjBJT->objParameters.xtb);
   pobjBJT->brx = 1 / Temp_brf(pobjBJT->objParameters.br, pobjBJT->objParameters.xtb);
   pobjBJT->vkf = (float)(pobjBJT->objParameters.nf * g_fVtVolt * log(pobjBJT->objParameters.nf * g_fVtVolt / pobjBJT->is));
   pobjBJT->vkr = (float)(pobjBJT->objParameters.nr * g_fVtVolt * log(pobjBJT->objParameters.nr * g_fVtVolt / pobjBJT->is));
   pobjBJT->vke = (float)(pobjBJT->objParameters.ne * g_fVtVolt * log(pobjBJT->objParameters.ne * g_fVtVolt / pobjBJT->ise));
   pobjBJT->vkc = (float)(pobjBJT->objParameters.nc * g_fVtVolt * log(pobjBJT->objParameters.nc * g_fVtVolt / pobjBJT->isc));

   InitCapacitor(&pobjBJT->be_cap);
   InitCapacitor(&pobjBJT->bc_cap);

   pobjBJT->vbe  = ROF(pobjBJT->objParameters.iter0) ? pobjBJT->objParameters.vbe0 : 0.98 * pobjBJT->vkf * iPolarity;
   pobjBJT->vbc  = ROF(pobjBJT->objParameters.iter0) ? pobjBJT->objParameters.vbc0 : 0.95 * pobjBJT->vkr * iPolarity;
   pobjBJT->cjev = pobjBJT->cjcv = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   BJT_SetDefaultParameters
//
// Overview:   Initializes the specified structure of diode parameters.
//
// Arguments:  pobjBJT [OUT] Pointer to the structure of BJT transistor.
//
///////////////////////////////////////////////////////////////////////////////

void BJT_SetDefaultParameters (stBJT* pobjBJT)
{
   stParBJT* pobjParameters = &pobjBJT->objParameters;

   pobjParameters->is    = (float)1e-16;
   pobjParameters->bf    = 100.0;
   pobjParameters->nf    = 1.0;
   pobjParameters->ise   = 0;
   pobjParameters->ne    = 1.5;
   pobjParameters->br    = 1.0;
   pobjParameters->nr    = 1.0;
   pobjParameters->isc   = 0;
   pobjParameters->nc    = 2.0;
   pobjParameters->rb    = 0;
   pobjParameters->re    = 0;
   pobjParameters->rc    = 0;
   pobjParameters->cje   = 0;
   pobjParameters->vje   = 0.75;
   pobjParameters->mje   = (float)0.33;
   pobjParameters->cjc   = 0;
   pobjParameters->vjc   = 0.75;
   pobjParameters->mjc   = (float)0.33;
   pobjParameters->fc    = 0.5;
   pobjParameters->tf    = 0;
   pobjParameters->xtf   = 0;
   pobjParameters->vtf   = 1000;
   pobjParameters->itf   = 0;
   pobjParameters->tr    = 0;
   pobjParameters->eg    = (float)1.11;
   pobjParameters->xti   = 3.0;
   pobjParameters->xtb   = 0;
   pobjParameters->vbe0  = 0;
   pobjParameters->vbc0  = 0;
   pobjParameters->iter0 = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Capacitor_BuildAC
//
// Overview:   Builds AC simulation for the specified capacitor.
//
// Arguments:  pobjCapacitor [IN] A reference to the structure of the specified
//                                capacitor.
//             fOmega        [IN] Omega factor.
//
///////////////////////////////////////////////////////////////////////////////

void Capacitor_BuildAC (stCapacitor* pobjCapacitor, float fOmega)
{
   SetCapacitorAC(pobjCapacitor->iPortA, pobjCapacitor->iPortB,
      pobjCapacitor->fCapacitance, fOmega);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Capacitor_BuildDC
//
// Overview:   Builds DC simulation for the specified capacitor.
//
// Arguments:  pobjCapacitor [IN] A reference to the structure of the specified
//                                capacitor.
//             fSimTime      [IN] A simulation time step.
//             wMode         [IN] A simulation mode.
//
///////////////////////////////////////////////////////////////////////////////

void Capacitor_BuildDC (stCapacitor* pobjCapacitor, float fSimTime, WORD wMode)
{
   SetCapacitorDC(pobjCapacitor->iPortA, pobjCapacitor->iPortB,
      pobjCapacitor->fCapacitance, &pobjCapacitor->stState, fSimTime, wMode);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Capacitor_InitSim
//
// Overview:   Initializes the specified capacitor.
//
// Arguments:  iPortA        [IN]  A port number of the first terminal.
//             iPortB        [IN]  A port number of the second terminal.
//             fCapacitance  [IN]  A capacitance (in Farads) of the specified
//                                 capacitor.
//             fV0           [IN]  Initial voltage.
//             iInitLCMode   [IN]  Kind of initialization.
//             pobjCapacitor [OUT] A reference to the structure of the specified
//                                 capacitor to be intialized.
//
///////////////////////////////////////////////////////////////////////////////

void Capacitor_InitSim (int iPortA, int iPortB, float fCapacitance, float fV0,
                        int iInitLCMode, stCapacitor* pobjCapacitor)
{
   pobjCapacitor->fCapacitance = fCapacitance;
   pobjCapacitor->iPortA       = iPortA;
   pobjCapacitor->iPortB       = iPortB;

   switch (iInitLCMode)
   {
   case LC_CLEAR: SetCapacitor(0., &pobjCapacitor->stState); break;
   case LC_SET:   SetCapacitor(fV0, &pobjCapacitor->stState); break;
   case LC_SOLVE: InitCapacitor(&pobjCapacitor->stState); break;
   default:       pobjCapacitor->stState.time = 0.0;
   }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Diode_BuildAC
//
// Overview:   Builds AC simulation for the specified diode.
//
// Arguments:  pobjDiode [IN] A reference to the structure of the specified diode.
//             fOmegap   [IN] Omega factor.
//
///////////////////////////////////////////////////////////////////////////////

void Diode_BuildAC (stDiode* pobjDiode, float fOmega)
{
   if (pobjDiode->ianode != pobjDiode->iAnode)
      CONDUCTANCE(pobjDiode->ianode, pobjDiode->iAnode, pobjDiode->ys);

   CONDUCTANCE(pobjDiode->iCathode, pobjDiode->ianode, pobjDiode->dn.yn + pobjDiode->db.yb + g_fMinAdmit);

   if (pobjDiode->cj >= 1e-18 || pobjDiode->objParameters.tt >= 1e-18)
      SetCapacitorAC(pobjDiode->ianode, pobjDiode->iCathode, pobjDiode->cjv, fOmega);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Diode_BuildDC
//
// Overview:   Builds DC simulation for the specified diode.
//
// Arguments:  pobjDiode [IN] A pointer to the structure of the specified diode.
//             fSimTime  [IN] Simulation step time.
//             wMode     [IN] Mode of simulation.
//
///////////////////////////////////////////////////////////////////////////////

void Diode_BuildDC (stDiode* pobjDiode, float fSimTime, WORD wMode)
{
   if (pobjDiode->ianode != pobjDiode->iAnode)
      CONDUCTANCE(pobjDiode->ianode, pobjDiode->iAnode, pobjDiode->ys);

   if (wMode & ITERATE)
   {
      InternalDiode(pobjDiode->is, pobjDiode->vkn, pobjDiode->objParameters.n * g_fVtVolt, pobjDiode->vac, &pobjDiode->dn);
      InternalReverceDiode(pobjDiode->objParameters.ibv, pobjDiode->objParameters.bv, pobjDiode->vkb, g_fVtVolt, pobjDiode->vac, &pobjDiode->db);
   }

   DC_CURRENT(pobjDiode->ianode, pobjDiode->iCathode, pobjDiode->dn.in + pobjDiode->db.ib);
   CONDUCTANCE(pobjDiode->iCathode, pobjDiode->ianode, pobjDiode->dn.yn + pobjDiode->db.yb + g_fMinAdmit);

   if (pobjDiode->cj >= 1e-18 || pobjDiode->objParameters.tt >= 1e-18)
   {
      if (wMode & ITERATE)
         pobjDiode->cjv = PN_Capacitor(pobjDiode->cj, pobjDiode->objParameters.tt, pobjDiode->objParameters.m, pobjDiode->objParameters.fc, pobjDiode->vj, pobjDiode->is, pobjDiode->objParameters.ibv, pobjDiode->objParameters.bv, (float)pobjDiode->vac);

      SetCapacitorDC(pobjDiode->ianode, pobjDiode->iCathode, pobjDiode->cjv, &pobjDiode->ac_cap, fSimTime, wMode);
   }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Diode_ErrorCheck
//
// Overview:   Check for possible error in calculation.
//
// Arguments:  pDiode [IN] A pointer to the structure of the specified diode.
//
///////////////////////////////////////////////////////////////////////////////

void Diode_ErrorCheck (stDiode* pobjDiode, double* pdVoltError)
{
   MaxErrEx(pobjDiode->ianode, pobjDiode->iCathode, &pobjDiode->vac, pdVoltError);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Diode_InitIntNodes
//
// Overview:   Initializes the specified diode.
//
// Arguments:  pobjDiode       [IN] A pointer to working structure of diode.
//             iAnode          [IN] An anode number.
//             iInternalAnode  [IN] An internal anode number.
//
// Returns:    0 - The internal anode wasn't created.
//             1 - The internal anode was created successfully.
//
///////////////////////////////////////////////////////////////////////////////

int Diode_InitIntNodes (stDiode* pobjDiode, int iAnode, int iInternalAnode)
{
   if (pobjDiode->objParameters.rs >= 1e-6)
   {
      pobjDiode->ys     = 1 / pobjDiode->objParameters.rs;
      pobjDiode->ianode = iInternalAnode;
      return 1;
   }
   
   pobjDiode->ianode = iAnode;
   return 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Diode_InitSim
//
// Overview:   Initializes the specified diode.
//
// Arguments:  iAnode       [IN]  A port number of the anode.
//             iCathode     [IN]  A port number of the cathode.
//             iInitLCMode  [IN]  Kind of initialization.
//             pobjDiode    [OUT] A reference to the structure of the specified
//                                diode to be intialized.
//
///////////////////////////////////////////////////////////////////////////////

void Diode_InitSim (int iAnode, int iCathode, int iInitLCMode, stDiode* pobjDiode)
{
   pobjDiode->iAnode   = iAnode;
   pobjDiode->iCathode = iCathode;
   SetTemp();
   pobjDiode->is  = Temp_is(pobjDiode->objParameters.is, pobjDiode->objParameters.n, pobjDiode->objParameters.eg, pobjDiode->objParameters.xti);
   pobjDiode->vj  = Temp_vj(pobjDiode->objParameters.vj);
   pobjDiode->cj  = Temp_cj(pobjDiode->objParameters.cjo, pobjDiode->objParameters.m, pobjDiode->vj / pobjDiode->objParameters.vj);
   pobjDiode->vkn = (float)(pobjDiode->objParameters.n * g_fVtVolt * log(pobjDiode->objParameters.n * g_fVtVolt / pobjDiode->is));
   pobjDiode->vkb = (float)(-g_fVtVolt * log(g_fVtVolt / pobjDiode->objParameters.ibv) - pobjDiode->objParameters.bv);
   InitCapacitor(&pobjDiode->ac_cap);
   pobjDiode->vac = ROF(pobjDiode->objParameters.iter0) ? pobjDiode->objParameters.vac0 : 0.85 * pobjDiode->vkn;
   pobjDiode->cjv = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Diode_SetDefaultParameters
//
// Overview:   Initializes the specified structure of diode parameters.
//
// Arguments:  pobjDiode [OUT] A pointer to the structure of the diode.
//
///////////////////////////////////////////////////////////////////////////////

void Diode_SetDefaultParameters (stDiode* pobjDiode)
{
   stParDiode* pobjParameters = &pobjDiode->objParameters;

   pobjParameters->is    = (float)1.0e-14;
   pobjParameters->rs    = (float)0;
   pobjParameters->n     = (float)1;
   pobjParameters->tt    = (float)0;
   pobjParameters->cjo   = (float)0;
   pobjParameters->vj    = (float)1;
   pobjParameters->m     = (float)0.5;
   pobjParameters->eg    = (float)1.11;
   pobjParameters->xti   = (float)3.0;
   pobjParameters->fc    = (float)0.5;
   pobjParameters->bv    = (float)1.0e3;
   pobjParameters->ibv   = (float)1.0e-3;
   pobjParameters->vac0  = (float)0.63;
   pobjParameters->iter0 = (float)0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Inductor_BuildAC
//
// Overview:   Builds AC simulation for the specified inductor.
//
// Arguments:  pobjInductor [IN] A pointer to the structure of the specified
//                               inductor.
//             fOmega       [IN] Omega factor.
//
///////////////////////////////////////////////////////////////////////////////

void Inductor_BuildAC (stInductor* pobjInductor, float fOmega)
{
   SetInductorAC(pobjInductor->iPortA, pobjInductor->iPortB,
      pobjInductor->fInductance, fOmega);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Inductor_BuildDC
//
// Overview:   Builds DC simulation for the specified inductor.
//
// Arguments:  pobjInductor [IN] A pointer to the structure of the specified
//                               inductor.
//             fSimTime     [IN] A simulation time step.
//             wMode        [IN] A simulation mode.
//
///////////////////////////////////////////////////////////////////////////////

void Inductor_BuildDC (stInductor* pobjInductor, float fSimTime, WORD wMode)
{
   SetInductorDC(pobjInductor->iPortA, pobjInductor->iPortB,
      pobjInductor->fInductance, &pobjInductor->stState, fSimTime, wMode);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Inductor_InitSim
//
// Overview:   Initializes the specified inductor.
//
// Arguments:  iPortA       [IN]  A port number of the first terminal.
//             iPortB       [IN]  A port number of the second terminal.
//             fInductance  [IN]  An inductance (in Henries) of the specified
//                                inductor.
//             fI0          [IN]  Initial current.
//             pobjInductor [OUT] A POINTER to the structure of the specified
//                               inductor to be intialized.
//
///////////////////////////////////////////////////////////////////////////////

void Inductor_InitSim (int iPortA, int iPortB, float fInductance, float fI0,
                        int iInitLCMode, stInductor* pobjInductor)
{
   pobjInductor->fInductance = fInductance;
   pobjInductor->iPortA      = iPortA;
   pobjInductor->iPortB      = iPortB;

   switch (iInitLCMode)
   {
   case LC_CLEAR: SetInductor(0., &pobjInductor->stState); break;
   case LC_SET:   SetInductor(fI0, &pobjInductor->stState); break;
   case LC_SOLVE: InitInductor(&pobjInductor->stState); break;
   default:       pobjInductor->stState.time = 0.0;
   }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   JFET_BuildAC
//
// Overview:   Builds AC simulation for the specified JFET.
//
// Arguments:  PobjJFET [IN] A POINTER to the structure of the specified JFET.
//             fOmega   [IN] Omega factor.
//
///////////////////////////////////////////////////////////////////////////////

void JFET_BuildAC (stJFET* pobjJFET, float fOmega)
{
   if (pobjJFET->idrn != pobjJFET->drn)
      CONDUCTANCE(pobjJFET->idrn, pobjJFET->drn, pobjJFET->yd);

   if (pobjJFET->isrc != pobjJFET->src)
      CONDUCTANCE(pobjJFET->isrc, pobjJFET->src, pobjJFET->ys);

   if (pobjJFET->igate != pobjJFET->gate)
      CONDUCTANCE(pobjJFET->igate, pobjJFET->gate, pobjJFET->yg);

   CONDUCTANCE(pobjJFET->idrn, pobjJFET->igate, pobjJFET->dgd.yn);
   CONDUCTANCE(pobjJFET->isrc, pobjJFET->igate, pobjJFET->dgs.yn);

   if (!pobjJFET->fet.rev)
   {
      CONDUCTANCE(pobjJFET->isrc, pobjJFET->idrn, pobjJFET->fet.b);
      TRANSCONDUCTANCE(pobjJFET->igate, pobjJFET->isrc, pobjJFET->idrn, pobjJFET->isrc, pobjJFET->fet.c);
   }
   else
   {
      CONDUCTANCE(pobjJFET->idrn, pobjJFET->isrc, pobjJFET->fet.b);
      TRANSCONDUCTANCE(pobjJFET->igate, pobjJFET->idrn, pobjJFET->isrc, pobjJFET->idrn, pobjJFET->fet.c);
   }
    
   if (pobjJFET->cgs >= 1e-18)
      SetCapacitorAC(pobjJFET->igate, pobjJFET->isrc, pobjJFET->cgsv, fOmega);

   if (pobjJFET->cgd >= 1e-18)
      SetCapacitorAC(pobjJFET->igate, pobjJFET->idrn, pobjJFET->cgdv, fOmega);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   JFET_BuildDC
//
// Overview:   Builds DC simulation for the specified JFET.
//
// Arguments:   objJFET  [IN] A POINTER to the structure of the specified JFET.
//             fSimTime  [IN] Simulation step time.
//             wMode     [IN] Mode of simulation.
//
///////////////////////////////////////////////////////////////////////////////

void JFET_BuildDC (stJFET* pobjJFET, float fSimTime, WORD wMode)
{
   if (pobjJFET->idrn != pobjJFET->drn)
      CONDUCTANCE(pobjJFET->idrn, pobjJFET->drn, pobjJFET->yd);

   if (pobjJFET->isrc != pobjJFET->src)
      CONDUCTANCE(pobjJFET->isrc, pobjJFET->src, pobjJFET->ys);

   if (pobjJFET->igate != pobjJFET->gate)
      CONDUCTANCE(pobjJFET->igate, pobjJFET->gate, pobjJFET->yg);

   if (wMode & ITERATE)
   {
      InternalDiode(pobjJFET->is, pobjJFET->vk, g_fVtVolt, pobjJFET->vgd * pobjJFET->iPolarity, &pobjJFET->dgd);
      InternalDiode(pobjJFET->is, pobjJFET->vk, g_fVtVolt, pobjJFET->vgs * pobjJFET->iPolarity, &pobjJFET->dgs);
      FieldEffect(pobjJFET->vds, pobjJFET->vgs, pobjJFET->vgd, pobjJFET->vto, pobjJFET->beta, pobjJFET->objParameters.lambda, pobjJFET->iPolarity, &pobjJFET->fet);
   }
   
   DC_CURRENT(pobjJFET->igate, pobjJFET->idrn, pobjJFET->dgd.in * pobjJFET->iPolarity);
   DC_CURRENT(pobjJFET->igate, pobjJFET->isrc, pobjJFET->dgs.in * pobjJFET->iPolarity);
   CONDUCTANCE(pobjJFET->idrn, pobjJFET->igate, pobjJFET->dgd.yn);
   CONDUCTANCE(pobjJFET->isrc, pobjJFET->igate, pobjJFET->dgs.yn);

   if (!pobjJFET->fet.rev)
   {
      CONDUCTANCE(pobjJFET->isrc, pobjJFET->idrn, pobjJFET->fet.b);
      TRANSCONDUCTANCE(pobjJFET->igate, pobjJFET->isrc, pobjJFET->idrn, pobjJFET->isrc, pobjJFET->fet.c);
      DC_CURRENT(pobjJFET->idrn, pobjJFET->isrc, pobjJFET->fet.a * pobjJFET->iPolarity);
   }
   else
   {
      CONDUCTANCE(pobjJFET->idrn, pobjJFET->isrc, pobjJFET->fet.b);
      TRANSCONDUCTANCE(pobjJFET->igate, pobjJFET->idrn, pobjJFET->isrc, pobjJFET->idrn, pobjJFET->fet.c);
      DC_CURRENT(pobjJFET->isrc, pobjJFET->idrn, pobjJFET->fet.a * pobjJFET->iPolarity);
   }
    
   if (pobjJFET->cgs >= 1e-18)
   {
      if (wMode & ITERATE)
        pobjJFET->cgsv = PN_Capacitor(pobjJFET->cgs, 0, 0.5, pobjJFET->objParameters.fc, pobjJFET->pb, pobjJFET->is, 0, 0, (float)(pobjJFET->vgs * pobjJFET->iPolarity));

      SetCapacitorDC(pobjJFET->igate, pobjJFET->isrc, pobjJFET->cgsv, &pobjJFET->gs_cap, fSimTime, wMode);
   }
   
   if (pobjJFET->cgd >= 1e-18)
   {
      if (wMode & ITERATE)
        pobjJFET->cgdv = PN_Capacitor(pobjJFET->cgd, 0, 0.5, pobjJFET->objParameters.fc, pobjJFET->pb, pobjJFET->is, 0, 0, (float)(pobjJFET->vgd * pobjJFET->iPolarity));
      SetCapacitorDC(pobjJFET->igate, pobjJFET->idrn, pobjJFET->cgdv, &pobjJFET->gd_cap, fSimTime, wMode);
    }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   JFET_ErrorCheck
//
// Overview:   Check for possible error in calculation.
//
// Arguments:  PobjJFET [IN] A POINTER to the structure of the specified JFET.
//
///////////////////////////////////////////////////////////////////////////////

void JFET_ErrorCheck (stJFET* pobjJFET, double* pdVoltError)
{
   MaxErrEx(pobjJFET->idrn, pobjJFET->isrc, &pobjJFET->vds, pdVoltError);
   MaxErrEx(pobjJFET->igate, pobjJFET->isrc, &pobjJFET->vgs, pdVoltError);
   MaxErrEx(pobjJFET->igate, pobjJFET->idrn, &pobjJFET->vgd, pdVoltError);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   JFET_InitIntNodes
//
// Overview:   Initializes the specified JFET.
//
// Arguments:  pobjJFET      [IN] A pointer to working structure of JFET.
//             iDrain        [IN] Drain terminal.
//             iGate         [IN] Gate terminal.
//             iSource       [IN] Source terminal.
//             iInternalNode [IN] An internal node number.
//
// Returns:    A number of created internal nodes.
//
///////////////////////////////////////////////////////////////////////////////

int JFET_InitIntNodes (stJFET* pobjJFET, int iDrain, int iGate, int iSource,
                       int iInternalNode)
{
   int iNodes = 0;

   pobjJFET->drn  = iDrain;
   pobjJFET->src  = iSource;
   pobjJFET->gate = iGate;

   pobjJFET->idrn  = iDrain;
   pobjJFET->isrc  = iSource;
   pobjJFET->igate = iGate;

   if (pobjJFET->objParameters.rd >= 1e-6)
   {
      pobjJFET->yd   = (float)(1.0 / pobjJFET->objParameters.rd);
      pobjJFET->idrn = iInternalNode + iNodes++;
   }

   if (pobjJFET->objParameters.rs >= 1e-6)
   {
      pobjJFET->ys   = (float)(1.0 / pobjJFET->objParameters.rs);
      pobjJFET->isrc = iInternalNode + iNodes++;
   }

   if (pobjJFET->objParameters.rg >= 1e-6)
   {
      pobjJFET->yg    = (float)(1.0 / pobjJFET->objParameters.rg);
      pobjJFET->igate = iInternalNode + iNodes++;
   }
   
   return iNodes;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   JFET_InitSim
//
// Overview:   Initializes the specified JFET.
//
// Arguments:  iInitLCMode [IN]  Kind of initialization.
//             pobjJFET    [OUT] A pointer to the structure of the specified
//                               JFET to be intialized.
//             iPolarity   [IN]  The polarity of JFET transistor.
//
///////////////////////////////////////////////////////////////////////////////

void JFET_InitSim (int iInitLCMode, stJFET* pobjJFET, int iPolarity)
{
   pobjJFET->iPolarity = iPolarity;
   SetTemp();
   pobjJFET->is   = Temp_is(pobjJFET->objParameters.is, 1.0, (float)1.11, 0.0);
   pobjJFET->vto  = pobjJFET->objParameters.vto + pobjJFET->objParameters.vtotc * (g_fTemp - 27);
   pobjJFET->beta = (float)(pobjJFET->objParameters.beta * pow(1.01, pobjJFET->objParameters.betatc * (g_fTemp - 27)));
   pobjJFET->pb   = Temp_vj(pobjJFET->objParameters.pb);
   pobjJFET->cgs  = Temp_cj(pobjJFET->objParameters.cgs, 0.5, pobjJFET->pb / pobjJFET->objParameters.pb);
   pobjJFET->cgd  = Temp_cj(pobjJFET->objParameters.cgd, 0.5, pobjJFET->pb / pobjJFET->objParameters.pb);
   pobjJFET->vk   = (float)(g_fVtVolt * log(g_fVtVolt / pobjJFET->is));
   InitCapacitor(&pobjJFET->gs_cap);
   InitCapacitor(&pobjJFET->gd_cap);
   pobjJFET->vgs  = ROF(pobjJFET->objParameters.iter0) ? pobjJFET->objParameters.vgs0 : 0.69 * pobjJFET->vk * pobjJFET->iPolarity;
   pobjJFET->vgd  = ROF(pobjJFET->objParameters.iter0) ? pobjJFET->objParameters.vgd0 : 0.70 * pobjJFET->vk * pobjJFET->iPolarity;
   pobjJFET->vds  = 0.0;
   pobjJFET->cgsv = pobjJFET->cgdv = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   JFET_SetDefaultParameters
//
// Overview:   Initializes the specified structure of diode parameters.
//
// Arguments:  pobjJFET [OUT] Pointer to the structure of JFET transistor.
//
///////////////////////////////////////////////////////////////////////////////

void JFET_SetDefaultParameters (stJFET* pobjJFET)
{
   stParJFET* pobjParameters = &pobjJFET->objParameters;

   pobjParameters->vto    = -2.0;
   pobjParameters->beta   = (float)1e-4;
   pobjParameters->lambda = 0;
   pobjParameters->rg     = 0;
   pobjParameters->rd     = 0;
   pobjParameters->rs     = 0;
   pobjParameters->is     = (float)1e-14;
   pobjParameters->cgd    = 0;
   pobjParameters->cgs    = 0;
   pobjParameters->pb     = 1.0;
   pobjParameters->fc     = 0.5;
   pobjParameters->vtotc  = 0;
   pobjParameters->betatc = 0;
   pobjParameters->vgs0   = 0;
   pobjParameters->vgd0   = 0;
   pobjParameters->iter0  = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   MOSFET_BuildAC
//
// Overview:   Builds AC simulation for the specified MOSFET.
//
// Arguments:  pobjMOSFET [IN] A pointer to the structure of the specified MOSFET.
//             fOmega     [IN] Omega factor.
//
///////////////////////////////////////////////////////////////////////////////

void MOSFET_BuildAC (stMOSFET* pobjMOSFET, float fOmega)
{
   if (pobjMOSFET->idrn != pobjMOSFET->drn)
      CONDUCTANCE(pobjMOSFET->idrn, pobjMOSFET->drn, pobjMOSFET->yd);
    
   if (pobjMOSFET->isrc != pobjMOSFET->src)
      CONDUCTANCE(pobjMOSFET->isrc, pobjMOSFET->src, pobjMOSFET->ys);
    
   if (pobjMOSFET->igate != pobjMOSFET->gate)
      CONDUCTANCE(pobjMOSFET->igate, pobjMOSFET->gate, pobjMOSFET->yg);
    
   if (pobjMOSFET->ibulk != pobjMOSFET->bulk)
      CONDUCTANCE(pobjMOSFET->ibulk, pobjMOSFET->bulk, pobjMOSFET->yb);

   CONDUCTANCE(pobjMOSFET->idrn, pobjMOSFET->ibulk, pobjMOSFET->dbd.yn);
   CONDUCTANCE(pobjMOSFET->isrc, pobjMOSFET->ibulk, pobjMOSFET->dbs.yn);
  
   if (!pobjMOSFET->fet.rev)
   {
      CONDUCTANCE(pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->fet.b);
      TRANSCONDUCTANCE(pobjMOSFET->igate, pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->fet.c);
   }
   else
   {
      CONDUCTANCE(pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->fet.b);
      TRANSCONDUCTANCE(pobjMOSFET->igate, pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->fet.c);
   }
    
   if (pobjMOSFET->objParameters.cgs >= 1e-18)
      SetCapacitorAC(pobjMOSFET->igate, pobjMOSFET->isrc, pobjMOSFET->objParameters.cgs, fOmega);
    
   if (pobjMOSFET->objParameters.cgd >= 1e-18)
      SetCapacitorAC(pobjMOSFET->igate, pobjMOSFET->idrn, pobjMOSFET->objParameters.cgd, fOmega);
    
   if (pobjMOSFET->objParameters.cgb >= 1e-18)
      SetCapacitorAC(pobjMOSFET->igate, pobjMOSFET->ibulk, pobjMOSFET->objParameters.cgb, fOmega);
    
   if (pobjMOSFET->cbd >= 1e-18)
      SetCapacitorAC(pobjMOSFET->ibulk, pobjMOSFET->idrn, pobjMOSFET->cbdv, fOmega);
    
   if (pobjMOSFET->cbs >= 1e-18)
      SetCapacitorAC(pobjMOSFET->ibulk, pobjMOSFET->isrc, pobjMOSFET->cbsv, fOmega);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   MOSFET_BuildDC
//
// Overview:   Builds DC simulation for the specified MOSFET.
//
// Arguments:  pobjMOSFET [IN] A pointer to the structure of the specified MOSFET.
//             fSimTime   [IN] Simulation step time.
//             wMode      [IN] Mode of simulation.
//
///////////////////////////////////////////////////////////////////////////////

void MOSFET_BuildDC (stMOSFET* pobjMOSFET, float fSimTime, WORD wMode)
{
   if (pobjMOSFET->idrn != pobjMOSFET->drn)
      CONDUCTANCE(pobjMOSFET->idrn, pobjMOSFET->drn, pobjMOSFET->yd);
    
   if (pobjMOSFET->isrc != pobjMOSFET->src)
      CONDUCTANCE(pobjMOSFET->isrc, pobjMOSFET->src, pobjMOSFET->ys);
    
   if (pobjMOSFET->igate != pobjMOSFET->gate)
      CONDUCTANCE(pobjMOSFET->igate, pobjMOSFET->gate, pobjMOSFET->yg);
    
   if (pobjMOSFET->ibulk != pobjMOSFET->bulk)
      CONDUCTANCE(pobjMOSFET->ibulk, pobjMOSFET->bulk, pobjMOSFET->yb);

   if (wMode & ITERATE)
   {
      InternalDiode(pobjMOSFET->is, pobjMOSFET->vk, g_fVtVolt, pobjMOSFET->vbd * pobjMOSFET->iPolarity, &pobjMOSFET->dbd);
      InternalDiode(pobjMOSFET->is, pobjMOSFET->vk, g_fVtVolt, pobjMOSFET->vbs * pobjMOSFET->iPolarity, &pobjMOSFET->dbs);
      FieldEffect(pobjMOSFET->vds, pobjMOSFET->vgs, pobjMOSFET->vgd, pobjMOSFET->vto, pobjMOSFET->beta, pobjMOSFET->objParameters.lambda, pobjMOSFET->iPolarity, &pobjMOSFET->fet);
   }
    
   DC_CURRENT(pobjMOSFET->ibulk, pobjMOSFET->idrn, pobjMOSFET->dbd.in * pobjMOSFET->iPolarity);
   DC_CURRENT(pobjMOSFET->ibulk, pobjMOSFET->isrc, pobjMOSFET->dbs.in * pobjMOSFET->iPolarity);
   CONDUCTANCE(pobjMOSFET->idrn, pobjMOSFET->ibulk, pobjMOSFET->dbd.yn);
   CONDUCTANCE(pobjMOSFET->isrc, pobjMOSFET->ibulk, pobjMOSFET->dbs.yn);
  
   if (!pobjMOSFET->fet.rev)
   {
      CONDUCTANCE(pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->fet.b);
      TRANSCONDUCTANCE(pobjMOSFET->igate, pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->fet.c);
      DC_CURRENT(pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->fet.a * pobjMOSFET->iPolarity);
   }
   else
   {
      CONDUCTANCE(pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->fet.b);
      TRANSCONDUCTANCE(pobjMOSFET->igate, pobjMOSFET->idrn, pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->fet.c);
      DC_CURRENT(pobjMOSFET->isrc, pobjMOSFET->idrn, pobjMOSFET->fet.a * pobjMOSFET->iPolarity);
   }
    
   if (pobjMOSFET->objParameters.cgs >= 1e-18)
      SetCapacitorDC(pobjMOSFET->igate, pobjMOSFET->isrc, pobjMOSFET->objParameters.cgs, &pobjMOSFET->gs_cap, fSimTime, wMode);
    
   if (pobjMOSFET->objParameters.cgd >= 1e-18)
      SetCapacitorDC(pobjMOSFET->igate, pobjMOSFET->idrn, pobjMOSFET->objParameters.cgd, &pobjMOSFET->gd_cap, fSimTime, wMode);
    
   if (pobjMOSFET->objParameters.cgb >= 1e-18)
      SetCapacitorDC(pobjMOSFET->igate, pobjMOSFET->ibulk, pobjMOSFET->objParameters.cgb, &pobjMOSFET->gb_cap, fSimTime, wMode);
    
   if (pobjMOSFET->cbd >= 1e-18)
   {
      if (wMode & ITERATE)
         pobjMOSFET->cbdv = PN_Capacitor(pobjMOSFET->cbd, 0, (float)0.5, pobjMOSFET->objParameters.fc, pobjMOSFET->pb, pobjMOSFET->is, 0, 0, (float)(pobjMOSFET->vbd * pobjMOSFET->iPolarity));
      
      SetCapacitorDC(pobjMOSFET->ibulk, pobjMOSFET->idrn, pobjMOSFET->cbdv, &pobjMOSFET->bd_cap, fSimTime, wMode);
   }
    
   if (pobjMOSFET->cbs >= 1e-18)
   {
      if (wMode & ITERATE)
         pobjMOSFET->cbsv = PN_Capacitor(pobjMOSFET->cbs, 0, 0.5, pobjMOSFET->objParameters.fc, pobjMOSFET->pb, pobjMOSFET->is, 0, 0, (float)(pobjMOSFET->vbs * pobjMOSFET->iPolarity));
      
      SetCapacitorDC(pobjMOSFET->ibulk, pobjMOSFET->isrc, pobjMOSFET->cbsv, &pobjMOSFET->bs_cap, fSimTime, wMode);
   }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   MOSFET_ErrorCheck
//
// Overview:   Check for possible error in calculation.
//
// Arguments:  pobjMOSFET [IN] A pointer to the structure of the specified MOSFET.
//
///////////////////////////////////////////////////////////////////////////////

void MOSFET_ErrorCheck (stMOSFET* pobjMOSFET, double* pdVoltError)
{  
   MaxErrEx(pobjMOSFET->idrn, pobjMOSFET->isrc, &pobjMOSFET->vds, pdVoltError);
   MaxErrEx(pobjMOSFET->igate, pobjMOSFET->isrc, &pobjMOSFET->vgs, pdVoltError);
   MaxErrEx(pobjMOSFET->igate, pobjMOSFET->idrn, &pobjMOSFET->vgd, pdVoltError);
   MaxErrEx(pobjMOSFET->ibulk, pobjMOSFET->idrn, &pobjMOSFET->vbd, pdVoltError);
   MaxErrEx(pobjMOSFET->ibulk, pobjMOSFET->isrc, &pobjMOSFET->vbs, pdVoltError);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   MOSFET_InitIntNodes
//
// Overview:   Initializes the specified MOSFET.
//
// Arguments:  pobjMOSFET     [IN] A pointer to working structure of MOSFET.
//             iInternalAnode [IN] An internal anode number.
//
// Returns:    0 - The internal anode wasn't created.
//             1 - The internal anode was created successfully.
//
///////////////////////////////////////////////////////////////////////////////

int MOSFET_InitIntNodes (stMOSFET* pobjMOSFET, int iInternalNode)
{
   int iNodes = 0;
   
   pobjMOSFET->idrn  = pobjMOSFET->drn;
   pobjMOSFET->igate = pobjMOSFET->gate;
   pobjMOSFET->isrc  = pobjMOSFET->src;
   pobjMOSFET->ibulk = pobjMOSFET->bulk;

   if (pobjMOSFET->objParameters.rd >= 1e-6)
   {
      pobjMOSFET->yd   = (float)(1.0 / pobjMOSFET->objParameters.rd);
      pobjMOSFET->idrn = iInternalNode + iNodes++;
   }

   if (pobjMOSFET->objParameters.rs >= 1e-6)
   {
      pobjMOSFET->ys   = (float)(1.0 / pobjMOSFET->objParameters.rs);
      pobjMOSFET->isrc = iInternalNode + iNodes++;
   }
    
   if (pobjMOSFET->objParameters.rg >= 1e-6)
   {
      pobjMOSFET->yg    = (float)(1.0 / pobjMOSFET->objParameters.rg);
      pobjMOSFET->igate = iInternalNode + iNodes++;
   }
   
   if (pobjMOSFET->objParameters.rb >= 1e-6)
   {
      pobjMOSFET->yb    = (float)(1.0 / pobjMOSFET->objParameters.rb);
      pobjMOSFET->ibulk = iInternalNode + iNodes++;
   }
   
   return iNodes;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   MOSFET_InitSim
//
// Overview:   Initializes the specified MOSFET.
//
// Arguments:  iDrain      [IN]  A port number of the drain.
//             iGate       [IN]  A port number of the base.
//             iSource     [IN]  A port number of the source.
//             iBulk       [IN]  A port number of the bulk.
//             iInitLCMode [IN]  Kind of initialization.
//             pobjMOSFET  [OUT] A pointer to the structure of the specified
//                               MOSFET to be intialized.
//             iPolarity   [IN]  The polarity of transistor (NMOS or PMOS).
//
///////////////////////////////////////////////////////////////////////////////

void MOSFET_InitSim (int iDrain, int iGate, int iSource, int iBulk,
                     int iInitLCMode, stMOSFET* pobjMOSFET, int iPolarity)
{
   pobjMOSFET->idrn      = iDrain;
   pobjMOSFET->igate     = iGate;
   pobjMOSFET->isrc      = iSource;
   pobjMOSFET->ibulk     = iBulk;
   pobjMOSFET->iPolarity = iPolarity;

   SetTemp();
   
   pobjMOSFET->is   = Temp_is(pobjMOSFET->objParameters.is, 1.0, (float)1.11, 0.0);
   pobjMOSFET->beta = (float)(pobjMOSFET->objParameters.wlr * (pobjMOSFET->objParameters.kp / 2) * pow(g_fTempRel, -3 / 2));
   pobjMOSFET->vto  = pobjMOSFET->objParameters.vto;
   pobjMOSFET->pb   = Temp_vj(pobjMOSFET->objParameters.pb);
   pobjMOSFET->cbs  = Temp_cj(pobjMOSFET->objParameters.cbs, 0.5, pobjMOSFET->pb / pobjMOSFET->objParameters.pb);
   pobjMOSFET->cbd  = Temp_cj(pobjMOSFET->objParameters.cbd, 0.5, pobjMOSFET->pb / pobjMOSFET->objParameters.pb);
   pobjMOSFET->vk   = (float)(g_fVtVolt * log(g_fVtVolt / pobjMOSFET->is));
   InitCapacitor(&pobjMOSFET->gs_cap);
   InitCapacitor(&pobjMOSFET->gd_cap);
   InitCapacitor(&pobjMOSFET->bs_cap);
   InitCapacitor(&pobjMOSFET->bd_cap);
   InitCapacitor(&pobjMOSFET->gb_cap);
   pobjMOSFET->vgs  = pobjMOSFET->vgd  = ROF(pobjMOSFET->objParameters.iter0) ? pobjMOSFET->objParameters.vgs0 : (1.1 * pobjMOSFET->vto * pobjMOSFET->iPolarity);
   pobjMOSFET->vds  = pobjMOSFET->vbs  = pobjMOSFET->vbd = 0.0;
   pobjMOSFET->cbdv = pobjMOSFET->cbsv = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   MOSFET_SetDefaultParameters
//
// Overview:   Initializes the specified structure of MOSFET parameters.
//
// Arguments:  pobjMOSFET [OUT] Pointer to the structure of MOSFET transistor.
//
///////////////////////////////////////////////////////////////////////////////

void MOSFET_SetDefaultParameters (stMOSFET* pobjMOSFET)
{
   stParMOSFET* pobjParameters = &pobjMOSFET->objParameters;

   pobjParameters->vto    = 0.0;
   pobjParameters->wlr    = 1.0;
   pobjParameters->kp     = (float)2e-5;
   pobjParameters->lambda = 0;
   pobjParameters->rg     = 0;
   pobjParameters->rd     = 0;
   pobjParameters->rs     = 0;
   pobjParameters->rb     = 0;
   pobjParameters->is     = (float)1e-14;
   pobjParameters->cgd    = 0;
   pobjParameters->cgs    = 0;
   pobjParameters->cbd    = 0;
   pobjParameters->cbs    = 0;
   pobjParameters->cgb    = 0;
   pobjParameters->pb     = (float)0.8;
   pobjParameters->fc     = 0.5;
   pobjParameters->vgs0   = 0;
   pobjParameters->iter0  = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Resistor_BuildAC
//
// Overview:   Builds AC simulation for the specified resistor.
//
// Arguments:  pobjResistor [IN] A pointer to the structure of the specified
//                               resistor.
//
///////////////////////////////////////////////////////////////////////////////

void Resistor_BuildAC (stResistor* pobjResistor)
{
   CONDUCTANCE(pobjResistor->iPortA, pobjResistor->iPortB, pobjResistor->fAdmittance);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Resistor_BuildDC
//
// Overview:   Builds DC simulation for the specified resistor.
//
// Arguments:  pobjResistor [IN] A pointer to the structure of the specified
//                               resistor.
//
///////////////////////////////////////////////////////////////////////////////

void Resistor_BuildDC (stResistor* pobjResistor)
{
   CONDUCTANCE(pobjResistor->iPortA, pobjResistor->iPortB, pobjResistor->fAdmittance);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Resistor_InitSim
//
// Overview:   Initializes the specified resistor.
//
// Arguments:  iPortA       [IN]  A port number of the first terminal.
//             iPortB       [IN]  A port number of the second terminal.
//             fResistance  [IN]  A resistance (in Ohms) of the specified
//                                resistor.
//             pobjResistor [OUT] A pointer to the structure of the specified
//                                resistor to be intialized.
//
///////////////////////////////////////////////////////////////////////////////

void Resistor_InitSim (int iPortA, int iPortB, float fResistance,
                       stResistor* pobjResistor)
{
   pobjResistor->iPortA      = iPortA;
   pobjResistor->iPortB      = iPortB;
   pobjResistor->fAdmittance = (float)(fabs(fResistance) >= 1e-6 ? 1.0 / fResistance : g_fMaxAdmit);
}


///////////////////////////////////////////////////////////////////////////////
//
// Function:   Resistor_TestAdmit
//
// Overview:   Computes the minimal and maximal admittances for the specified
//             resistor.
//
// Arguments:  fResistance [IN] A resistance (in Ohms) of the specified
//                              resistor.
//
///////////////////////////////////////////////////////////////////////////////

void Resistor_TestAdmit (float fResistance, float* pfMinAdmit, float* pfMaxAdmit)
{
   TestResist(fResistance, pfMinAdmit, pfMaxAdmit);
}
